
import SwiftUI
 
final class AtmosphereLightViewModel: ObservableObject {
    
    // 支持的所有效果类型
    enum Effect: String {
        case normal, breathe, fluid, beat, rainbow
    }
    
    let effectList: [Effect] = [.normal, .breathe, .fluid, .beat, .rainbow]
    
    let colorList: [Color] = [.red, .orange, .green, .pink]
    
    @Published var effect = Effect.breathe
    @Published var color = Color.orange
    @Published var luminance = 0.0
    @Published var follow = false
}

struct AtmosphereLightView: View {
    
    // 绑定上层的状态
    @Binding var show: Bool
    
    // 事件回传上层
    let action: () -> Void
    
    // viewModel 进行数据逻辑处理和提供
    @StateObject private var viewModel = AtmosphereLightViewModel()
    
    @State private var bottom = -510.0
    @State private var op = 0.0
     
    
    private func dismiss(active: Bool) {
        withAnimation {
            bottom = -510
            op = 0
        }
        after(0.5) {
            show = false
            if active { action() }
        }
    }
    
    var body: some View {
        ZStack {
            Color.black.opacity(op).edgesIgnoringSafeArea(.all)
                .onTapGesture {
                    dismiss(active: false)
                }
            
            VStack {
                Spacer()
                
                VStack(spacing: 32) {
                    Text("atmosphere")
                        .font(.system(size: 16).bold())
                        .foregroundColor(Color(red: 0.06, green: 0.06, blue: 0.06))
                    Toggle("follow", isOn: $viewModel.follow)
                        .padding(.horizontal, 16)
                    
                    light
                    
                    effect
                    
                    color
                    
                    Button(action: {
                        dismiss(active: true)
                    }, label: {
                        Text("determin")
                            .font(.system(size: 16))
                            .foregroundColor(.white)
                            .frame(maxWidth: .infinity, maxHeight: 48, alignment: .center)
                            .background(Color(red: 0.31, green: 0.67, blue: 0.49).cornerRadius(12, antialiased: true))
                            .padding(.top, 8)
                            .padding(.horizontal, 16)
                            
                    })
                }
                .padding(.vertical, 16)
                .background(Color(red: 0.97, green: 0.97, blue: 0.97).cornerRadius(16, antialiased: true))
            }
            .padding(.horizontal, 10)
            .padding(.bottom, bottom)
            .foregroundColor(Color(red: 0.40, green: 0.40, blue: 0.40))
            .font(.system(size: 14), weight: .semibold)
            .edgesIgnoringSafeArea(.bottom)
        }
        .onAppear {
            // 弹簧动画初始化
            withAnimation(.interpolatingSpring(mass: 0.95, stiffness: 140, damping: 16)) {
                bottom = 25
                op = 0.6
            }
        }
    }
}

extension AtmosphereLightView {
    
    var light: some View {
         
        VStack(spacing: 8) {
            Text("light")
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.leading, 16)
            HStack(spacing: 15) {
                GeometryReader { geo in
                    
                    ZStack(alignment: .leading) {
                        Capsule()
                            .frame(height: 32)
                            .foregroundColor(Color(red: 0.90, green: 0.90, blue: 0.90))
                        Capsule()
                            .frame(width: geo.size.width * viewModel.luminance + (1 - viewModel.luminance) * 32, height: 32)
                            .foregroundColor(Color(red: 0.29, green: 0.72, blue: 0.51))
                            .opacity(viewModel.luminance == 0 ? 0 : 1)
                            .overlay {
                                Circle()
                                    .fill(Color.white)
                                    .offset(x: (geo.size.width * viewModel.luminance) / 2 - viewModel.luminance * 15)
                            }
                    }
                    
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .onChanged { value in
                                
                                var x = value.location.x
                                if x < 0 { x = 0 }
                                if x > geo.size.width { x = geo.size.width }
                                viewModel.luminance = x / geo.size.width
                            }
                            .onEnded({ value in
                                printXY(">>>--- valueeee: \(value)", obj: self)
                                var x = value.location.x
                                if x < 0 { x = 0 }
                                if x > geo.size.width { x = geo.size.width }
                                viewModel.luminance = x / geo.size.width
                            })
                        
                    )
                }
                Text(String(format: "%.0f%%", viewModel.luminance * 100.0))
                    .font(.system(size: 16), weight: .medium)
                    .foregroundColor(Color(red: 0.20, green: 0.20, blue: 0.20))
                    .frame(width: 62, height: 32)
                    .background(Color.white.cornerRadius(8, antialiased: true))
            }
            .frame(height: 32)
            .padding(.horizontal, 16)
        }
    }
    
    var effect: some View {
        VStack(alignment: .leading, spacing: 0) {
            Text("effect")
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.leading, 16)
            ScrollView(.horizontal, showsIndicators: false, content: {
                HStack(spacing: 0) {
                    ForEach(0..<viewModel.effectList.count, id: \.self) { index in
                        VStack(spacing: 5) {
                            let active = viewModel.effectList[index] == viewModel.effect
                            
                            ZStack {
                                Ellipse()
                                    .fill(active ? Color(red: 0.29, green: 0.72, blue: 0.51) : Color(red: 0.90, green: 0.90, blue: 0.90))
                                    .frame(width: 38, height: 38)
                                    .shadow(color: Color(red: 0, green: 0, blue: 0, opacity: active ? 0.10 : 0.0), radius: 6)
                                if active {
                                    Ellipse()
                                        .stroke(Color.white, lineWidth: 2.50)
                                        .frame(width: 26, height: 26)
                                }
                            }
                            .frame(width: 38, height: 38)
                            
                            Text(viewModel.effectList[index].rawValue)
                                .lineLimit(1)
                                .font(.system(size: 12))
                                .foregroundColor(active ? Color(red: 0.25, green: 0.64, blue: 0.45) : Color(red: 0.60, green: 0.60, blue: 0.60))
                        }
                        .frame(width: 72)
                        .padding(.top, 8)
                        .background(Color(red: 0.97, green: 0.97, blue: 0.97))
                        .onTapGesture {
                            withAnimation(.default) {
                                viewModel.effect = viewModel.effectList[index]
                            }
                        }
                    }
                }
            })
        }
    }
    
    var color: some View {
        VStack(alignment: .leading, spacing: 0) {
            Text("color")
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.leading, 16)
            ScrollView(.horizontal, showsIndicators: false, content: {
                HStack(spacing: 0) {
                    ForEach(0..<viewModel.colorList.count, id: \.self) { index in
                        
                        let active = viewModel.colorList[index] == viewModel.color
                        ZStack {
                            Ellipse()
                                .fill(viewModel.colorList[index])
                                .frame(width: 32, height: 32)
                                .shadow(color: Color(red: 0, green: 0, blue: 0, opacity: active ? 0.10 : 0.0), radius: 6)
                            if active {
                                Ellipse()
                                    .stroke(Color.white, lineWidth: 2.50)
                                    .frame(width: 24, height: 24)
                            }
                        }
                        .frame(width: 32, height: 32)
                        .frame(width: 48)
                        .padding(.vertical, 8)
                        .background(Color(red: 0.97, green: 0.97, blue: 0.97))
                        .onTapGesture {
                            withAnimation(.default) {
                                viewModel.color = viewModel.colorList[index]
                            }
                        }
                    }
                }
                .padding(.leading, 8)
            })
        }
    }
}
